package com.woniu.woniu.life.gateway.filter;

import cn.hutool.core.text.AntPathMatcher;
import cn.hutool.jwt.JWTException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.common.api.api.CommonResult;
import com.woniu.common.api.api.enums.ResultCode;
import com.woniu.common.api.jwt.JwtUtils;
import com.woniu.common.api.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class AuthFilter implements GlobalFilter, Ordered {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 请求头中传递参数的名称
     */
    public static final String AUTHORIZATION_HEADER = "Authorization";

    public static final String BEARER = "Bearer ";

    @Autowired
    private JwtUtils jwtUtils;

    // TODO：redisUtil报错
//    @Autowired
//    private RedisUtil redisUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 拦截请求的资源
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath();
        AntPathMatcher matcher = new AntPathMatcher();
        // 如果需要验证，就要获取token

        String header = request.getHeaders().getFirst(AUTHORIZATION_HEADER);
        if (!StringUtils.isEmpty(header)) {
            // 获取请求头中的token
            String token = header.replace(BEARER, "");
            // 验证token
            try {
                boolean verify = false;
                // TODO 等待verify方法
                // jwtUtils.verify(token);
                if (!verify) {
                    log.info("token 无效");
                    return responseError(response);
                }
            } catch (JWTException e) {
                log.info("token 格式错误");
                return responseError(response);
            }
            String userId = (String) jwtUtils.getClaim(token, "userId");
            Object redisToken = null;
            // TODO：没有redisUtil
//            redisUtil.getCacheObject("auth::user::" + userId);
            if (Objects.isNull(redisToken)) {
                log.info("token 过期");
                return responseError(response);
            }
            // token 续期
            resetTokenExperationTime(userId, redisToken);
            // 重写请求头，方便业务系统从请求头获取用户ID
            ServerHttpRequest.Builder builder = request.mutate();
            request = builder.header("userId", userId).build();
        } else {
            if (matcher.match("/**/auth/**", path)) {
                log.info("无授权token");
                return responseError(response);
            }
        }

        return chain.filter(exchange);
    }

    private void resetTokenExperationTime(String userId, Object redisToken) {
        // TODO：没有redisUtil
//        redisUtil.setCacheObject("auth::user::" + userId, redisToken, 24000, TimeUnit.SECONDS);
    }

    private Mono<Void> responseError(ServerHttpResponse httpResponse) {
//        JSONObject message = new JSONObject();
//        message.set("code", ResultCode.PERMISSION_NO_ACCESS.getCode());
//        message.set("message", ResultCode.PERMISSION_NO_ACCESS.getMessage());
//        byte[] date = message.toString().getBytes(StandardCharsets.UTF_8);
//        DataBuffer dataBuffer = httpResponse.bufferFactory().wrap(date);
//        return httpResponse.writeWith(Mono.just(dataBuffer));
        CommonResult commonResult = null;
        // TODO CommonResult没有failure方法
        // CommonResult.failure(ResultCode.PERMISSION_NO_ACCESS);
        try {
            byte[] data = objectMapper.writer().writeValueAsBytes(commonResult);
            DataBuffer dataBuffer = httpResponse.bufferFactory().wrap(data);
            httpResponse.getHeaders().add("Content-Type", "application/json,charset=UTF-8");
            return httpResponse.writeWith(Mono.just(dataBuffer));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public int getOrder() {
        return 0;
    }
}
